lexer grammar ContinuationLexer;
options {
language=CSharp3;
}


@members{
public bool insideMultiLineComment { get; set; }
public int nestingLevel { get; set; }
public bool insideWysiwygString { get; set; }
public bool insideAlternateWysiwygString { get; set; }
public bool insideDoubleQuotedString { get; set; }
public bool insideHexadecimalString { get; set; }

public int numHexDigits { get; set; }
}

//Tokens

//Terminated by */ or End of Line
ContinueMultiLineComment
	:	{insideMultiLineComment}?=> 
		(('*' ~'/')=> '*' 
			| ~('*' | EndOfLineFragment | EndOfFileFragment))* 
		('*/' {insideMultiLineComment = false;}
			| EndOfLineFragment)
	;

//Terminated by End of Line +/ or /+
ContinueNestingBlockComment
	:	{nestingLevel > 0}?=> 
		(('/' ~'+')=> '/'
			| ('+' ~'/')=> '+'
			| ~('/' | '+' | EndOfLineFragment | EndOfFileFragment))* 
		(EndOfLineFragment 
			| '+/' {--nestingLevel;} 
			| '/+' {++nestingLevel;})
	;

ContinueWysiwygString
	:	{insideWysiwygString}?=> 
		WysiwygCharacter* 
		(EndOfLineFragment 
			| '"' StringPostfix? {insideWysiwygString = false;})
	;

ContinueAlternateWysiwygString
	:	{insideAlternateWysiwygString}?=> 
		AlternateWysiwygCharacter* 
		(EndOfLineFragment
			| '`' StringPostfix? {insideAlternateWysiwygString = false;})
	;

ContinueDoubleQuotedString
	:	{insideDoubleQuotedString}?=> 
		DoubleQuotedCharacter* 
		(EndOfLineFragment
			| '"' StringPostfix? {insideDoubleQuotedString = false;})
	;

ContinueHexadecimalString
	:	{insideHexadecimalString}?=> 
		(HexadecimalDigit {++numHexDigits;} | WhiteSpace)* 
		(EndOfLineFragment
			| '"' StringPostfix? {insideHexadecimalString = false; numHexDigits = 0;} {numHexDigits \% 2 == 0}?)
	;


//End of tokens, Start of fragments

/*
Visual Studio eats up (doesn't pass to me) the normal end of line Strings:
'\n' '\r' and '\r\n'  But since I manually append '\n' to the Strings VS passes me, look for that.
*/
fragment
EndOfLineFragment
	:	'\n' | '\u2029' | '\u2028'
	;

fragment
EndOfFileFragment
	:	('\u0000' | '\u001A')
	;

fragment
WysiwygCharacter
	:	~('"' | EndOfLineFragment | EndOfFileFragment)
	;

fragment
AlternateWysiwygCharacter
	:	~('`' | EndOfLineFragment | EndOfFileFragment)
	;

fragment
DoubleQuotedCharacter
	:	EscapeSequence
	|	~('"' | EndOfLineFragment | EndOfFileFragment)
	;
	
fragment
StringPostfix
	:	'c'|'w'|'d'
	;

fragment
EscapeSequence
	:	'\\' ('\''|'"'|'?'|'\\'|'a'|'b'|'f'|'n'|'r'|'t'|'v'|EndOfFileFragment)
	|	'\\x' HexadecimalDigit HexadecimalDigit
	|	'\\' OctalDigit OctalDigit OctalDigit
	|	'\\' OctalDigit OctalDigit
	|	'\\' OctalDigit
	|	'\\u' HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit
	|	'\\U' HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit
	;

fragment
OctalDigit
	:	'0'..'7'
	;

fragment
HexadecimalDigit
	:	'0'..'9'|'a'..'f'|'A'..'F'
	;

WhiteSpace
	:	('\u0020' | '\u0009' | '\u000B' | '\u000C')
	;
